package com.goldsign.pay.common.security;

import com.goldsign.pay.common.util.HexStr;

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

/**
 * 常用加解密算法辅助类
 * 
 * @author zmj
 * 
 */
public class SecurityHelper {
	
	public static final String keyIndex = "13";
    public static final String algorithm = "MD5withRSA";
    
	/**
	 * Des加密,非自动补位
	 * 
	 * @param data
	 *            待加密数据,长度必须为8 的整数倍
	 * @param key
	 *            密钥 8字节,若大于8字节,则多余字节无效
	 * @return des加密密文
	 */
	public static byte[] encryptDES(byte[] data, byte[] key) {
		byte[] encryptedData = null;

		try {

			DESKeySpec dks = new DESKeySpec(key);
			// 创建一个密匙工厂，然后用它把DESKeySpec转换成一个SecretKey对象
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			SecretKey sk = keyFactory.generateSecret(dks);

			// Cipher对象实际完成加密操作
			Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");

			// 用密匙初始化Cipher对象
			cipher.init(Cipher.ENCRYPT_MODE, sk);

			// 执行加密操作
			encryptedData = cipher.doFinal(data);
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}

		return encryptedData;

	}

	/**
	 * des解密
	 * 
	 * @param data
	 *            待解密数据
	 * @param key
	 *            密钥 8字节
	 * @return 解密后的数据
	 */
	public static byte[] decryptDES(byte[] data, byte[] key) {
		byte[] decryptedData = null;
		try {
			DESKeySpec dks = new DESKeySpec(key);
			// 创建一个密匙工厂，然后用它把DESKeySpec转换成一个SecretKey对象
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			SecretKey sk = keyFactory.generateSecret(dks);
			// Cipher对象实际完成加密操作
			Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
			cipher.init(Cipher.DECRYPT_MODE, sk);
			// 执行加密操作
			decryptedData = cipher.doFinal(data);
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}

		return decryptedData;
	}

	/**
	 * 3des加密(待完善)
	 * @deprecated 请用encrypt3DES2()方法代替
	 * @param data
	 *            待加密数据
	 * @param key
	 *            密钥 24字节(若所给为16字节,则拷贝前8字节补充)
	 * @return
	 */
	public static byte[] encrypt3DES(byte[] data, byte[] key) {
		try {
			String algorithm = "DESede/ECB/PKCS7Padding";
			// 生成密钥
			byte[] key24 = key;
			if(key.length == 16){
				key24 = new byte[24];
				System.arraycopy(key, 0, key24, 0, 16);
				System.arraycopy(key, 0, key24, 16, 8);
			}
			SecretKey deskey = new SecretKeySpec(key24, algorithm);
			// 加密
			Cipher c1 = Cipher.getInstance(algorithm);
			c1.init(Cipher.ENCRYPT_MODE, deskey);
			return c1.doFinal(data);
		} catch (NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		} catch (NoSuchPaddingException e2) {
			e2.printStackTrace();
		} catch (Exception e3) {
			e3.printStackTrace();
		}
		return null;
	}

	/**
	 * 3des解密(待完善)
	 * @deprecated 请用decrypt3DES2()方法代替
	 * @param data
	 *            待解密数据
	 * @param key
	 *            密钥 24字节(若所给为16字节,则拷贝前8字节补充)
	 * @return
	 */
	public static byte[] decrypt3DES(byte[] data, byte[] key) {
		try {
			String algorithm = "DESede/ECB/PKCS7Padding";
			// 生成密钥
			byte[] key24 = key;
			if(key.length == 16){
				key24 = new byte[24];
				System.arraycopy(key, 0, key24, 0, 16);
				System.arraycopy(key, 0, key24, 16, 8);
			}
			SecretKey deskey = new SecretKeySpec(key24, algorithm);
			// 解密
			Cipher c1 = Cipher.getInstance(algorithm);
			c1.init(Cipher.DECRYPT_MODE, deskey);
			return c1.doFinal(data);
		} catch (NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		} catch (NoSuchPaddingException e2) {
			e2.printStackTrace();
		} catch (Exception e3) {
			e3.printStackTrace();
		}
		return null;
	}
	/**
	 * 3des加密,使用3重des
	 * @param data
	 * @param key
	 * @return
	 */
	public static byte[] encrypt3DES2(byte[] data, byte[] key) {
		byte[] result = null;
		byte[] key1 = new byte[8];
		byte[] key2 = new byte[8];
		
		System.arraycopy(key, 0, key1, 0, 8);
		System.arraycopy(key, 8, key2, 0, 8);
		
		result = encryptDES(data,key1);
		result = decryptDES(result,key2);
		result = encryptDES(result,key1);
		
		return result;
	}
	/**
	 * 3des解密,使用3重des
	 * @param data
	 * @param key
	 * @return
	 */
	public static byte[] decrypt3DES2(byte[] data, byte[] key) {
		byte[] result = null;
		byte[] key1 = new byte[8];
		byte[] key2 = new byte[8];
		
		System.arraycopy(key, 0, key1, 0, 8);
		System.arraycopy(key, 8, key2, 0, 8);
		
		result = decryptDES(data,key1);
		result = encryptDES(result,key2);
		result = decryptDES(result,key1);
		
		return result;
	}
	
	/**
	 * AES加密
	 * 
	 * @param data
	 *            待加密数据
	 * @param key
	 *            密钥
	 * @return
	 */
	public static byte[] encryptAES(byte[] data, byte[] key) {
		try {
			/*KeyGenerator kgen = KeyGenerator.getInstance("AES");
			SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
			secureRandom.setSeed(key);
			kgen.init(128, secureRandom);
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec sk = new SecretKeySpec(enCodeFormat, "AES");
			Cipher cipher = Cipher.getInstance("AES");// 创建密码器
			cipher.init(Cipher.ENCRYPT_MODE, sk);// 初始化
			*/
			//KeyGenerator kgen = KeyGenerator.getInstance("AES");
            //kgen.init(128, new SecureRandom(key));
            SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/Nopadding");
            //IvParameterSpec iv = new IvParameterSpec(IV.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
			return cipher.doFinal(data); // 加密并返回
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}
	/**
	 * AES解密
	 * @param data 待解密数据
	 * @param key 密钥
	 * @return
	 */
	public static byte[] decryptAES(byte[] data, byte[] key) {
		try {
			/*KeyGenerator kgen = KeyGenerator.getInstance("AES");
			SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
			secureRandom.setSeed(key);
			kgen.init(128, secureRandom);
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec sk = new SecretKeySpec(enCodeFormat, "AES");
			Cipher cipher = Cipher.getInstance("AES");// 创建密码器
			cipher.init(Cipher.DECRYPT_MODE, sk);// 初始化
			return cipher.doFinal(data); // 加密
			*/
			SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/Nopadding");
            //IvParameterSpec iv = new IvParameterSpec(IV.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            return cipher.doFinal(data); // 完成解密
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}
	/**
	 * md5加密
	 * @param data 待加密数据
	 * @return md5加密摘要
	 */
	public static byte[] md5Encrypt(byte[] data){
		try {
			MessageDigest messageDigest = MessageDigest.getInstance("MD5");
			byte[] plainText = data;
			messageDigest.update(plainText);
			return messageDigest.digest();
		} catch (NoSuchAlgorithmException e1) {
			e1.printStackTrace();			
		}
		return null;
	}
	/**
	 * md5加密,返回16进制串
	 * @param data 待加密数据
	 * @return 加密后的16进制字符串,若加密后不足16字节,则前补0
	 */
	public static String getMd5Hex(byte[] data){
		String md5 = HexStr.bufferToHex(md5Encrypt(data));
		while(md5.length() < 32){
			md5 = "0" + md5;
		}
		return md5;
	}
	
	/**
	 * 计算循环冗余码
	 * @param data 
	 * @param init 初始值
	 * @return	16进制的1字节数据
	 */
	public static String lrc(byte[] data,byte init){
		byte bRet = init;
		for(byte b :data){
			bRet ^= b;
		}
		return HexStr.bufferToHex(new byte[]{bRet});
	}
	
}
